package util

import "errors"

type InviteKey struct {
	CHARS        []string // CHARS
	CHARS_LENGTH int
	CODE_LENGTH  int // 邀请码长度
	SLAT         int // 随机数据
	PRIME1       int // PRIME1 与 CHARS 的长度 L互质，可保证 ( id * PRIME1) % L 在 [0,L)上均匀分布
	PRIME2       int // PRIME2 与 CODE_LENGTH 互质，可保证 ( index * PRIME2) % CODE_LENGTH  在 [0，CODE_LENGTH）上均匀分布
}

func (ik InviteKey) Encode(id int) (code string) {
	//补位
	id = id*ik.PRIME1 + ik.SLAT
	//将 id 转换成32进制的值
	var b = make([]int, ik.CODE_LENGTH)
	//32进制数
	b[0] = id
	for i := 0; i < ik.CODE_LENGTH-1; i++ {
		b[i+1] = b[i] / ik.CHARS_LENGTH
		//按位扩散
		b[i] = (b[i] + i*b[0]) % ik.CHARS_LENGTH
	}
	b[5] = (b[0] + b[1] + b[2] + b[3] + b[4]) * ik.PRIME1 % ik.CHARS_LENGTH

	//进行混淆
	var codeIndexArray = make([]int, ik.CODE_LENGTH)
	for i := 0; i < ik.CODE_LENGTH; i++ {
		codeIndexArray[i] = b[i*ik.PRIME2%ik.CODE_LENGTH]
	}
	var res string
	for _, v := range codeIndexArray {
		res += ik.CHARS[v]
	}
	return res
}

func (ik InviteKey) findIndex(c string) int {
	for i := 0; i < ik.CHARS_LENGTH; i++ {
		if ik.CHARS[i] == c {
			return i
		}
	}
	return -1
}

func (ik InviteKey) Decode(code string) (id int, err error) {
	if len(code) != int(ik.CODE_LENGTH) {
		return 0, errors.New("验证码不合法")
	}
	//将字符还原成对应数字
	var a = make([]int, ik.CODE_LENGTH)
	for i := 0; i < ik.CODE_LENGTH; i++ {
		var c = code[i : i+1]
		index := ik.findIndex(c)
		if index == -1 {
			//异常字符串
			return 0, errors.New("异常字符串")
		}
		a[i*ik.PRIME2%ik.CODE_LENGTH] = index
	}

	b := make([]int, ik.CODE_LENGTH)
	for i := ik.CODE_LENGTH - 2; i >= 0; i-- {
		b[i] = (a[i] - a[0]*i + ik.CHARS_LENGTH*i) % ik.CHARS_LENGTH
	}

	var res int
	for i := ik.CODE_LENGTH - 2; i >= 0; i-- {
		res += b[i]
		if i > 0 {
			res *= ik.CHARS_LENGTH
		} else {
			res *= 1
		}
	}
	return (res - ik.SLAT) / ik.PRIME1, nil
}
